package com.lw.sbdemo2.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 文件工具类
 * @author sjf
 */
public class FileUtil {

    private static final Logger logger = LoggerFactory.getLogger(FileUtil.class);

    private final static int BUFFER = 1024;

    /**
     * 功 能: 移动文件(只能移动文件) 参 数: strSourceFileName:指定的文件全路径名 strDestDir: 移动到指定的文件夹 返回值: 如果成功true;否则false
     *
     * @param strSourceFileName
     * @param strDestDir
     * @return
     */
    public static boolean copyTo(String strSourceFileName, String strDestDir) {
        File fileSource = new File(strSourceFileName);
        File fileDest = new File(strDestDir);

        // 如果源文件不存或源文件是文件夹
        if (!fileSource.exists() || !fileSource.isFile()) {
            logger.debug("源文件[" + strSourceFileName + "],不存在或是文件夹!");
            return false;
        }

        // 如果目标文件夹不存在
        if (!fileDest.isDirectory() || !fileDest.exists()) {
            if (!fileDest.mkdirs()) {
                logger.debug("目录文件夹不存，在创建目标文件夹时失败!");
                return false;
            }
        }

        try {
            String strAbsFilename = strDestDir + File.separator + fileSource.getName();

            FileInputStream fileInput = new FileInputStream(strSourceFileName);
            FileOutputStream fileOutput = new FileOutputStream(strAbsFilename);

            logger.debug("开始拷贝文件");

            int count = -1;

            long nWriteSize = 0;
            long nFileSize = fileSource.length();

            byte[] data = new byte[BUFFER];

            while (-1 != (count = fileInput.read(data, 0, BUFFER))) {

                fileOutput.write(data, 0, count);

                nWriteSize += count;

                long size = (nWriteSize * 100) / nFileSize;
                long t = nWriteSize;

                String msg = null;

                if (size <= 100 && size >= 0) {
                    msg = "\r拷贝文件进度:   " + size + "%   \t" + "\t   已拷贝:   " + t;
                    logger.debug(msg);
                } else if (size > 100) {
                    msg = "\r拷贝文件进度:   " + 100 + "%   \t" + "\t   已拷贝:   " + t;
                    logger.debug(msg);
                }

            }

            fileInput.close();
            fileOutput.close();

            logger.debug("拷贝文件成功!");
            return true;

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 功 能: 删除指定的文件 参 数: 指定绝对路径的文件名 strFileName 返回值: 如果删除成功true否则false;
     *
     * @param strFileName
     * @return
     */
    public static boolean delete(String strFileName) {
        File fileDelete = new File(strFileName);

        if (!fileDelete.exists() || !fileDelete.isFile()) {
            logger.debug(strFileName + "不存在!");
            return false;
        }

        return fileDelete.delete();
    }

    /**
     * 功 能: 移动文件(只能移动文件) 参 数: strSourceFileName: 是指定的文件全路径名 strDestDir: 移动到指定的文件夹中 返回值: 如果成功true; 否则false
     *
     * @param strSourceFileName
     * @param strDestDir
     * @return
     */
    public static boolean moveFile(String strSourceFileName, String strDestDir) {
        if (copyTo(strSourceFileName, strDestDir))
            return delete(strSourceFileName);
        else
            return false;
    }

    /**
     * 功 能: 创建文件夹 参 数: strDir 要创建的文件夹名称 返回值: 如果成功true;否则false
     *
     * @param strDir
     * @return
     */
    public static boolean makeDir(String strDir) {
        File fileNew = new File(strDir);

        if (!fileNew.exists()) {
            return fileNew.mkdirs();
        } else {
            return true;
        }
    }

    /**
     * 功 能: 删除文件夹 参 数: strDir 要删除的文件夹名称 返回值: 如果成功true;否则false
     *
     * @param strDir
     * @return
     */
    public static boolean removeDir(String strDir) {
        File rmDir = new File(strDir);
        if (rmDir.isDirectory() && rmDir.exists()) {
            String[] fileList = rmDir.list();

            for (int i = 0; i < fileList.length; i++) {
                String subFile = strDir + File.separator + fileList[i];
                File tmp = new File(subFile);
                if (tmp.isFile())
                    tmp.delete();
                else if (tmp.isDirectory())
                    removeDir(subFile);
            }
            rmDir.delete();
        } else {
            return false;
        }
        return true;
    }

    /**
     * 文件下载
     *
     * @param filePath
     * @param fileName
     * @param request
     * @param response
     */
    public static void downLoadFile(String filePath, String fileName, HttpServletRequest request, HttpServletResponse response) throws Exception {
        FileInputStream fileInputStream = null;
        try {
            File file = new File(filePath);
            long fileLength = file.length();
            // 设置下载参数
            fileName = encodeFilename(request, fileName);
            response.reset();
            response.setHeader("Content-Disposition", "attachment; " + fileName);
            response.addHeader("Content-Length", "" + fileLength);
            //response.setContentType("application/octet-stream;charset=UTF-8");

            response.setContentType("application/x-msdownload");

            fileInputStream = new FileInputStream(file);
            OutputStream out = response.getOutputStream();
            // 读文件
            int iBufferSize = 65000;
            byte[] buffer = new byte[65000];
            long lReadLen = 0;
            while (lReadLen < fileLength) {
                int lRead = fileInputStream.read(buffer, 0, iBufferSize);
                lReadLen += lRead;
                out.write(buffer, 0, lRead);
            }
            out.flush();
        } catch (Exception e) {
            throw new Exception(e);
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     * 文件下载解决文件名乱码问题，对文件名进行字符转换
     *
     * @param request
     * @param fileName
     * @return
     */
    public static String encodeFilename(HttpServletRequest request, String fileName) {
        String rtn = "";
        try {
            String userAgent = request.getHeader("USER-AGENT");
            String new_filename = URLEncoder.encode(fileName, "UTF8");
            // 如果没有UA，则默认使用IE的方式进行编码，因为毕竟IE还是占多数的
            rtn = "filename=\"" + new_filename + "\"";

            if (userAgent != null) {
                userAgent = userAgent.toLowerCase();
                // IE浏览器，只能采用URLEncoder编码
                if (userAgent.indexOf("msie") != -1) {
                    rtn = "filename=\"" + new_filename + "\"";
                }
                // Opera浏览器只能采用filename*
                else if (userAgent.indexOf("opera") != -1) {
                    rtn = "filename*=UTF-8''" + new_filename;
                }
                // Safari浏览器，只能采用ISO编码的中文输出
                else if (userAgent.indexOf("safari") != -1) {
                    rtn = "filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO8859-1") + "\"";
                }
                // Chrome浏览器，只能采用MimeUtility编码或ISO编码的中文输出
                else if (userAgent.indexOf("applewebkit") != -1) {
                    // new_filename = MimeUtility.encodeText(fileName, "UTF8", "B"); 备注：应用服务器可能采用自带jdk
                    new_filename = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
                    rtn = "filename=\"" + new_filename + "\"";
                }
                // FireFox浏览器，可以使用MimeUtility或filename*或ISO编码的中文输出
                else if (userAgent.indexOf("mozilla") != -1) {
                    rtn = "filename*=UTF-8''" + new_filename;
                }
            }

        } catch (UnsupportedEncodingException e) {
            try {
                rtn = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
            } catch (UnsupportedEncodingException e1) {
                // e1.printStackTrace();
            }
            // e.printStackTrace();
        }
        return rtn;
    }

    /**
     * 根据文本路径获取文件的内容字节
     * @param path
     * @return
     * @throws Exception
     */
    public static byte[] readFile(String path) throws Exception {
        File file = new File(path);
        byte[] bytes = null;
        if (file != null) {
            InputStream is = new FileInputStream(file);
            int length = (int) file.length();
            if (length > Integer.MAX_VALUE) // 当文件的长度超过了int的最大值
            {
                System.out.println("this file is max ");
                return null;
            }
            bytes = new byte[length];
            int offset = 0;
            int numRead = 0;
            while (offset < bytes.length
                    && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
                offset += numRead;
            }
            // 如果得到的字节长度和file实际的长度不一致就可能出错了
            if (offset < bytes.length) {
                System.out.println("file length is error");
                return null;
            }
            is.close();
        }
        return bytes;
    }

    /**
     * 根据文本路径获取文件的内容
     * @param path
     * @return
     * @throws Exception
     */
    public static String readFileContent(String path) throws Exception {
        byte[] bytes = readFile(path);
        return new String(bytes);
    }

    public static void main(String[] args) {

        // 创建目录
        String dirName = "C:/test";
        FileUtil.createDir(dirName);
        // 创建文件
        String fileName = dirName + "/temp/tempFile.txt";
        FileUtil.createFile(fileName);
        // 创建临时文件
        String prefix = "temp";
        String surfix = ".txt";
        FileUtil.createTempFile(prefix, surfix, dirName);

        try {
            String dateStr2 = null;
            String c = (String) dateStr2;
            System.out.println(c);
            //System.out.println(readFileContent("C:\\Users\\Administrator\\Desktop\\XMLFile2转换错误.xml"));
//			
//			int firstIndex=replaceText.indexOf("<E01XmlIn>")+10;
//			int lastIndex=replaceText.indexOf("</E01XmlIn>")+1;
//			String subStr=replaceText.substring(firstIndex,lastIndex);
//			String subStr1=subStr;
//			int subFirsIndex=subStr1.indexOf("{cdata_prefix}")+15;
//			subStr1=subStr1.replace(subStr1.substring(subFirsIndex-13,subFirsIndex-1), "<![CDATA[");
//			int subLastIndex=subStr1.lastIndexOf("{cdata_postfix}")+1;
//			subStr1=subStr1.replace(subStr1.substring(subLastIndex,subLastIndex+14), "]]>");
//			replaceText=replaceText.replace(subStr, subStr1);
            //replaceText.replace(replaceText.substring(replaceText.indexOf("<E01XmlIn>"),), newChar)
            System.out.println("===============================");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建单个文件
     * @param destFileName    目标文件名
     * @return 创建成功，返回true，否则返回false
     */
    public static boolean createFile(String destFileName) {
        File file = new File(destFileName);
        if (file.exists()) {
            System.out.println("创建单个文件" + destFileName + "失败，目标文件已存在！");
            return false;
        }
        if (destFileName.endsWith(File.separator)) {
            System.out.println("创建单个文件" + destFileName + "失败，目标文件不能为目录！");
            return false;
        }
        // 判断目标文件所在的目录是否存在
        if (!file.getParentFile().exists()) {
            // 如果目标文件所在的文件夹不存在，则创建父文件夹
            System.out.println("目标文件所在目录不存在，准备创建它！");
            if (!file.getParentFile().mkdirs()) {
                System.out.println("创建目标文件所在的目录失败！");
                return false;
            }
        }
        // 创建目标文件
        try {
            if (file.createNewFile()) {
                System.out.println("创建单个文件" + destFileName + "成功！");
                return true;
            } else {
                System.out.println("创建单个文件" + destFileName + "失败！");
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out
                    .println("创建单个文件" + destFileName + "失败！" + e.getMessage());
            return false;
        }
    }

    /**
     * 创建目录
     * @param destDirName   目标目录名
     * @return 目录创建成功放回true，否则返回false
     */
    public static boolean createDir(String destDirName) {
        File dir = new File(destDirName);
        if (dir.exists()) {
            System.out.println("创建目录" + destDirName + "失败，目标目录已存在！");
            return false;
        }
        if (!destDirName.endsWith(File.separator)) {
            destDirName = destDirName + File.separator;
        }
        // 创建目标目录
        if (dir.mkdir()) {
            System.out.println("创建目录" + destDirName + "成功！");
            return true;
        } else {
            System.out.println("创建目录" + destDirName + "失败！");
            return false;
        }
    }

    /**
     * 创建临时文件
     * @param prefix    临时文件名的前缀
     * @param suffix    临时文件名的后缀
     * @param dirName   临时文件所在的目录，如果输入null，则在用户的文档目录下创建临时文件
     * @return 临时文件创建成功返回true，否则返回false
     */
    public static String createTempFile(String prefix, String suffix,
                                        String dirName) {
        File tempFile = null;
        if (dirName == null) {
            try {
                // 在默认文件夹下创建临时文件
                tempFile = File.createTempFile(prefix, suffix);
                // 返回临时文件的路径
                return tempFile.getCanonicalPath();
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("创建临时文件失败!" + e.getMessage());
                return null;
            }
        } else {
            File dir = new File(dirName);
            // 如果临时文件所在目录不存在，首先创建
            if (!dir.exists()) {
                if (FileUtil.createDir(dirName)) {
                    System.out.println("创建临时文件失败，不能创建临时文件所在的目录！");
                    return null;
                }
            }
            try {
                // 在指定目录下创建临时文件
                tempFile = File.createTempFile(prefix, suffix, dir);
                return tempFile.getCanonicalPath();
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("创建临时文件失败!" + e.getMessage());
                return null;
            }
        }
    }

    public static void fileOuputStreamDemo(File f, String str) {

        FileOutputStream o = null;
        BufferedOutputStream bos = null;
        DataOutputStream dos = null;

        try {
            //流通常可以使用File文件对象或String路径字符串进行构造
            //true表示如果文件已经存在，没执行程序一次便往文件追加一次内容，
            //false表示每一次的执行结果会覆盖文件上一次执行结果，默认是false
            o = new FileOutputStream(f, true);

            //把fileOutputStream封装成具有缓冲功能的文件输出流，操作基本一致
            bos = new BufferedOutputStream(o);

            //字节流写入
            bos.write(str.getBytes());

            //DataOutputStream提供了写入任意对象的能力
            dos = new DataOutputStream(o);
            String tempStr = "DataOutputStream 方式写入\r\n";
            dos.write(tempStr.getBytes("utf-8"));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (dos != null) {
                try {
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
